#include "messiah/messiah_loader_tga.h"
#include "fileio/fileio.h"
#include "fileio/ifile.h"
#include "external/tinyxml/tinyxml2.h"
#include "public/build.h"

#include <iostream>
#include <cassert>

namespace renderit
{
	namespace messiah
	{
		loader_tga::loader_tga(const char * dirpath)
			: color_(nullptr)
		{
			dirpath_ = dirpath;
		}

		loader_tga::~loader_tga()
		{
			if (color_) {
				delete[] color_;
				color_ = nullptr;
			}
		}

		int loader_tga::width() const
		{
			return width_;
		}

		int loader_tga::height() const
		{
			return height_;
		}

		char * loader_tga::color_array()
		{
			return (char*)color_;
		}

		bool loader_tga::load()
		{
			std::string xml_path = fileio::join(dirpath_, "texture.xml");
			std::string data_path = fileio::join(dirpath_, "texture.data");

			// 1. Load XML
			tinyxml2::XMLDocument doc;
			if (doc.LoadFile(xml_path.c_str()))	{
				std::cout << "messiah::loader_tga.load() failed:" << xml_path << std::endl;
				return false;
			}

			tinyxml2::XMLElement* root_elem = doc.RootElement();
			tinyxml2::XMLElement* entity_elem = root_elem->FirstChildElementMultiLevel("Texture2DInfo/Root/Entity");
			if (!entity_elem) {
				return false;
			}

			tinyxml2::XMLUtil::ToInt(entity_elem->GetChildText("Width", "0"), &width_);
			tinyxml2::XMLUtil::ToInt(entity_elem->GetChildText("Height", "0"), &height_);

			assert(strcmp(entity_elem->GetChildText("Format", ""), "R8G8B8A8") == 0);

			// 2. Load Data
			fileio::ifile* data_file = fileio::open(data_path.c_str(), fileio::EOpen_Exist | fileio::EOpen_Read);
			if (!data_file) {
				return false;
			}

			uint64 size = data_file->size();
			assert(size == 4 * width_ * height_);

			color_ = new TgaColor[width_ * height_];
			int size_read = data_file->read((char*)color_, size);
			data_file->close();
			return size_read == size;
		}

		bool loader_tga::save()
		{
			// 1. Save XML
			{
				// TODO ...
			}

			// 2. Save Data
			std::string data_path = fileio::join(dirpath_, "texture.data");
			fileio::ifile* data_file = fileio::open(data_path.c_str(), fileio::EOpen_Write);
			if (!data_file) {
				return false;
			}

			bool b = data_file->write((char*)color_, 4 * width_ * height_);
			data_file->close();
			return b;
		}
	}
}